#include "texture.h"

/**
 * 17.3.12 - Steven Hartin - Added some simple debug messages into the code
 */

CTexture::CTexture(string path, const LPDIRECT3DDEVICE9 &device,
                   int nWidth, int nHeight):
    m_szPath(path), 
    m_pTexture(nullptr),
    m_nWidth(nWidth),
    m_nHeight(nHeight),
    m_bPermanent(false)
{
    /**
     * Constructor, Create a new texture on the heap and set the class to point 
     * to it. Then create a texture from the file path passed in.
     *
     * @param string path The path to the texture to load.
     * @param LPDIRECT3DDEVICE9 device The device to create the texture to.
     * @param int nWidth The width of the texture
     * @param int nHeight THe height of the texture
     */
    loadTexture(m_szPath, device, nWidth, nHeight);
}

CTexture::CTexture(const CTexture &rhs) :
    m_pTexture(nullptr),
    m_bPermanent(false)
{
    /**
     * Constructor, Create a new texture from the texture passed in.
     *
     *@param LPDIRECT3DTEXTURE9 texture A texture to inialise the CTexture with.
     */
    m_pTexture = rhs.m_pTexture;
    m_nHeight = rhs.m_nHeight;
    m_nWidth = rhs.m_nWidth;
}

CTexture::~CTexture()
{
    /**
     * Release the textures
     */
    if (m_pTexture != nullptr)
    {
        m_pTexture->Release();
    }
}

CTexture::CTexture(LPDIRECT3DTEXTURE9 texture) :
    m_pTexture(nullptr),
    m_nHeight(D3DPOOL_DEFAULT),
    m_nWidth(D3DPOOL_DEFAULT)
{
    /**
     * Copy the texture information from the texture passed in, create a
     * dynamic copy on the heap and assign the refernce count to 1. There is
     * no way of knowing if this texture has already been loaded, so we can't
     * obtain another reference, we can only create a new reference to the
     * texture.
     *
     * @param LPDIRECT3DTEXTURE9 texture The direct x texture to copy.
     */
    m_pTexture = texture;
}


LPDIRECT3DTEXTURE9 CTexture::getTexture() const 
{
    /**
     * @return LPDIRECT3DTEXTURE9 The texture.
     */ 
    return m_pTexture;
}

HRESULT CTexture::loadTexture(string path, LPDIRECT3DDEVICE9 device,
                              int nWidth, int nHeight) 
{
    /**
     * Load the texture from a given path on the given device.
     *
     * @param string path The path to the texture to load.
     * @param LPDIRECT3DDEVICE9 device The device to create the texture to.
     */
    HRESULT hr(D3DXCreateTextureFromFileEx( 
        device,
        m_szPath.c_str(), 
        D3DX_DEFAULT_NONPOW2,
        D3DX_DEFAULT_NONPOW2, 
        D3DX_FROM_FILE,
        D3DUSAGE_RENDERTARGET,
        D3DFMT_FROM_FILE,
        D3DPOOL_DEFAULT,
        D3DX_DEFAULT,
        D3DX_DEFAULT,
        0,
        &m_Info,
        NULL,
        &m_pTexture));

    if (FAILED(hr))
    {
        stringstream sstream;
        sstream << "Failed to load texture at path: "
                << path
                << "\n";
        MessageBox(nullptr, sstream.str().c_str(), "CTexture::loadTexture()",
                   MB_OK);
        m_pTexture = nullptr;
        return hr;
    }

    m_nHeight = m_Info.Height;
    m_nWidth = m_Info.Width;

    if (m_nHeight <= 0 || m_nWidth <= 0)
    {
        stringstream sstream;
        sstream << "Incorrect texture information for texture at path: "
                << path
                << "\n";
        MessageBox(nullptr, sstream.str().c_str(), "CTexture::loadTexture()",
                   MB_OK);
        m_pTexture = nullptr;
        return hr;
    }

    device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
    device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);

    //return D3DXCreateTextureFromFile(device, m_szPath.c_str(), 
    //                                     &m_pTexture);
    return hr;
}

void CTexture::applyTexture(int nTextureIndex, LPDIRECT3DDEVICE9 pDevice) const
{
    /**
     * Applys the texture to a texture index in the device.
     *
     * @param int nTextureIndex The texture index to apply the texture to (0-7)
     * @param LPDIRECT3DDEVICE9 pDevice The device to apply it to
     */
    if (m_pTexture != nullptr)
    {
        pDevice->SetTexture(nTextureIndex, m_pTexture);
    }
}

int CTexture::getWidth() const
{
    /**
     * @return int Width of the texture
     */
    return m_nWidth;
}

int CTexture::getHeight() const
{
    /**
     * @return int Height of the texture
     */
    return m_nHeight;
}

void CTexture::setPermanent(bool bPermanent)
{
    m_bPermanent = bPermanent;
}

bool CTexture::isPermanent() const
{
    return m_bPermanent;
}